/*
 * LoRA.c
 *
 *  Created on: May 4, 2020
 *      Author: daniel
 */

#include "LoRA.h"
#include "radio.h"
#include "sx126x.h"

#include "stm32l0xx_hal.h"

#include <stdio.h>
#include <string.h>

#include "data_struct.h"

extern uint8_t		receiveBufferSize;
extern uint8_t		receiveBuffer[MAX_LORA_BUFFER_SIZE];

void OnTxDone(void);
void OnRxDone(void);
void OnTxTimeout(void);
void OnRxTimeout(void);
void OnRxError(IrqErrorCode_t errorCode);
void OnCadDone( bool channelActivityDetected);

RadioCallbacks_t callbacks = { &OnTxDone,        // txDone
		&OnRxDone,        // rxDone
		NULL,             // rxPreambleDetect
		NULL,             // rxSyncWordDone
		NULL,             // rxHeaderDone
		&OnTxTimeout,     // txTimeout
		&OnRxTimeout,     // rxTimeout
		&OnRxError,       // rxError
		NULL,       // cadDone
		};

PacketParams_t PacketParams;
PacketStatus_t PacketStatus;

ModulationParams_t modulationParams;

#define RF_FREQUENCY  433000000 // Hz

#define TX_OUTPUT_POWER   14 //The range of the output power is [-18..+13] dBm
//#define TX_OUTPUT_POWER   22 //The range of the output power is [-18..+13] dBm

#define TX_TIMEOUT_VALUE                            0xFFFF // ms
//#define RX_TIMEOUT_VALUE                            12800 // 200ms
//#define RX_TIMEOUT_VALUE                            6400 // 100ms
//#define RX_TIMEOUT_VALUE                            2560 // 40ms
#define RX_TIMEOUT_VALUE                            3200 // 50ms


const uint16_t RxIrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
const uint16_t TxIrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;

// rx timeout callbak
static RXtimeout_callback		rxtimeout = NULL;
static void*					rxtimeout_data = NULL;

void LoRA_Init() {
	modulationParams.PacketType = PACKET_TYPE_LORA;
	modulationParams.Params.LoRa.SpreadingFactor = LORA_SF9;
	modulationParams.Params.LoRa.Bandwidth = LORA_BW_500;
	modulationParams.Params.LoRa.CodingRate = LORA_CR_4_7;

	PacketParams.PacketType = PACKET_TYPE_LORA;
	PacketParams.Params.LoRa.PreambleLength = 0x08;
	PacketParams.Params.LoRa.HeaderType = LORA_PACKET_VARIABLE_LENGTH;
	PacketParams.Params.LoRa.PayloadLength = 0;
	PacketParams.Params.LoRa.CrcMode = LORA_CRC_ON;
	PacketParams.Params.LoRa.InvertIQ = LORA_IQ_NORMAL;

	sx1262_Init();
	sx1262_SetRegulatorMode(USE_DCDC);

	sx1262_SetStandby(STDBY_RC);
//	sx1262_SetStandby(STDBY_XOSC);
	sx1262_SetPacketType(modulationParams.PacketType);
	sx1262_SetModulationParams(&modulationParams);
	sx1262_SetPacketParams(&PacketParams);

	sx1262_SetRfFrequency( RF_FREQUENCY);
	sx1262_SetBufferBaseAddresses(0x00, 0x00);
	sx1262_SetPaConfig(0x04, 0x07, 0x00, 0x01);
	sx1262_SetTxParams( TX_OUTPUT_POWER, RADIO_RAMP_20_US);

	sx1262_SetDioIrqParams(RxIrqMask | TxIrqMask, RxIrqMask | TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE);

	sx1262_SetLoRaSymbNumTimeout(0);
}

void LoRA_ISR() {
	sx1262_ProcessIrqs();
}

void OnTxDone(void) {
	receiveBufferSize = 0;

	sx1262_SetRxBoosted( RX_TIMEOUT_VALUE );

	HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2);
}

void OnRxDone(void) {
	int RssiValue, SnrValue;
	PacketStatus_t packetStatus;
	sx1262_GetPacketStatus(&packetStatus);
	RssiValue = packetStatus.Params.LoRa.RssiPkt;
	SnrValue = packetStatus.Params.LoRa.SnrPkt;

	// TODO:更新PWS端的RSSI和SNR，等待下一次回传

	receiveBufferSize = 0;
	sx1262_GetPayload(receiveBuffer, &receiveBufferSize, sizeof(receiveBuffer));

	HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2);
}

void OnTxTimeout(void) {
}

void OnRxTimeout(void) {
	if (rxtimeout != NULL)
	{
		rxtimeout(rxtimeout_data);
	}
	HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2);
}

void OnRxError(IrqErrorCode_t errorCode) {
	if (rxtimeout != NULL)
	{
		rxtimeout(rxtimeout_data);
	}
}

void OnCadDone( bool channelActivityDetected) {
}

void LoRA_Loop() {
	sx1262_ProcessIrqs();
}

void LoRA_TX(const uint8_t* buffer, uint8_t bufferSize, RXtimeout_callback rxtimeout_callback, void* data)
{
	rxtimeout = rxtimeout_callback;
	rxtimeout_data = data;

	PacketParams.Params.LoRa.PayloadLength = bufferSize;
	sx1262_SetPacketParams(&PacketParams);
	sx1262_SendPayload((uint8_t*)buffer, bufferSize, 0xFFFF);
}

